﻿using System;
using System.Collections.Generic;
using EasyLinkerSDK;
using EasyLinkerSDK.Client.Message;
using EasyLinkerSDK.Common.Json;
using EasyLinkerSDK.Common.Tools;
using EasyLinkerSDK.Enum;
using EasyLinkerSDK.Model.Client.Common;
using EasyLinkerSDK.Model.Client.Common.Interface;
using EasyLinkerSDK.Model.Client.Control;
using EasyLinkerSDK.Model.Client.Query;
using EasyLinkerSDK.Model.Info;
using EasyLinkerSDK.Model.Server.Common.Interface;
using EasyLinkerSDK.Model.Server.Common.ServerError;
using EasyLinkerSDK.Model.Server.Control;
using EasyLinkerSDK.Model.Server.Query;
using EasyLinkerSDK.Model.User;

namespace Demo
{
    class Program
    {
        static ClientInfo _clientInfo = new ClientInfo()
        {
            DeviceType = DeviceType.@switch,
            ProtocolType = ProtocolType.Tcp, //You can use Tcp or Mqtt
            Server = "127.0.0.1",
            DeviceId = "ca68722ce0323306",
            UserId = "770702827",
            Key = "ed6438afa9106b64c3abb65fb639b1da",
            IsReconnect = true,
        };

        static EasyLinkerClient _client = null;

        static void Main(string[] args)
        {
            _client = new EasyLinkerClient(_clientInfo, _clientInfo.ProtocolType);
            _client.DoMessageReceived += MessageReceived;
            _client.DoClientLog += ClientLog;
            if (_client.Start())
            {
                Console.WriteLine("已经连接到EasyLinker服务器...");
                while (true)
                {
                    string read = Console.ReadLine();
                    if (read == "exit" || read == "stop")
                    {
                        if (!_client.Stop())
                        {
                            Console.WriteLine("主动断开连接失败...");
                        }
                        break;
                    }
                }
            }
            else
            {
                Console.WriteLine("服务器连接失败，请检查用户名或密码是否正确...");
            }
            Console.WriteLine("Over...Please enter any key to exit...");
            Console.ReadKey(false);
        }

        private static void ClientLog(object sender, Exception ex)
        {
            if (ex == null)
            {
                Console.WriteLine(sender.ToString());
            }
            else
            {
                Console.WriteLine(sender.ToString() + " Exception:" + ex.Message);
            }
        }

        private static void MessageReceived(IServerMessage message)
        {
            Console.WriteLine("Request:" + JsonHelper.SerializeObject(message));
            switch (message.Type)
            {
                case MessageType.Control:
                    _client.Send(ProcessControlCmd(message));
                    break;
                case MessageType.Query:
                    _client.Send(ProcessQueryCmd(message));
                    break;
                case MessageType.Error:
                case MessageType.Success:
                    if (message is ServerError error)
                    {
                        if (error.Type == MessageType.Success)
                        {
                            Console.WriteLine($"[{DateTime.Now.ToString()}]Success");
                        }
                        else
                        {
                            Console.WriteLine($"Error code:{error.Data.Code} message:{error.Data.Message}");
                        }
                    }
                    break;
                case MessageType.Msg:
                    if (message is ServerError msg)
                    {
                        Console.WriteLine($"MessageType:{msg.Type}");
                    }
                    break;
            }
        }

        private static IClientMessage ProcessControlCmd(IServerMessage message)
        {
            if (message.Type != MessageType.Control)
            {
                return ErrorMessageBuilder.BuildClientError(_clientInfo, message, ClientErrorType.MSGTYPE_NOT_SUPPORT);
            }
            switch (message.Action)
            {
                case ActionName.TurnOn:
                    if (message is PowerControl _)
                    {
                        return BuildControlState(message, PowerState.On);
                    }
                    else
                    {
                        return ErrorMessageBuilder.BuildClientError(_clientInfo, message, ClientErrorType.ACTION_NOT_SUPPORT);
                    }
                case ActionName.TurnOff:
                    if (message is PowerControl _)
                    {
                        return BuildControlState(message, PowerState.Off);
                    }
                    else
                    {
                        return ErrorMessageBuilder.BuildClientError(_clientInfo, message, ClientErrorType.ACTION_NOT_SUPPORT);
                    }
                default:
                    return ErrorMessageBuilder.BuildClientError(_clientInfo, message, ClientErrorType.NOT_SUPPORT_FUNCTION);

            }
        }

        private static IClientMessage ProcessQueryCmd(IServerMessage message)
        {
            if (message.Type != MessageType.Query)
            {
                return ErrorMessageBuilder.BuildClientError(_clientInfo, message, ClientErrorType.MSGTYPE_NOT_SUPPORT);
            }
            if (!(message is EasyLinkerSDK.Model.Server.Query.QueryResult))
            {
                return ErrorMessageBuilder.BuildClientError(_clientInfo, message, ClientErrorType.MSGTYPE_NOT_SUPPORT);
            }
            EasyLinkerSDK.Model.Server.Query.QueryResult query = message as EasyLinkerSDK.Model.Server.Query.QueryResult;
            switch (query.Action)
            {
                case ActionName.Query:
                    return BuildQueryData(message, new List<PropertiyItem>()
                    {
                        new PropertiyItem()
                        {
                            Name = PropertiyType.temperature,
                            Value = new Random().Next(0,50).ToString()+"."+new Random().Next(0,10),
                        },
                        new PropertiyItem()
                        {
                            Name = PropertiyType.color,
                            Value = SupportControlColor.Blue.ToString(),
                        }
                    });
                case ActionName.QueryTemperature:
                    return BuildQueryData(message, new List<PropertiyItem>()
                    {
                        new PropertiyItem()
                        {
                            Name = PropertiyType.temperature,
                            Value = new Random().Next(0,50).ToString()+"."+new Random().Next(0,10),
                        }
                    });
                default:
                    return ErrorMessageBuilder.BuildClientError(_clientInfo, message, ClientErrorType.NOT_SUPPORT_FUNCTION);

            }
        }

        private static IClientMessage BuildControlState(IServerMessage message, PowerState power, List<PropertiyItem> values = null)
        {
            ControlState state = new ControlState()
            {
                Device = _clientInfo.DeviceType,
                Uid = _clientInfo.UserId,
                Key = _clientInfo.Key,
                ProtocolType = _clientInfo.ProtocolType,
                Type = MessageType.Control,
                Action = ActionName.TurnOn,
                MessageId = message.MessageId,
                DeviceId = message.DeviceId,
                Time = Time.Timestamp(),
                Data = new ControlStateData()
                {
                    PowerState = power,
                    Values = values,
                },
            };
            return state;
        }

        private static IClientMessage BuildQueryData(IServerMessage message, List<PropertiyItem> values = null)
        {
            if (values.Count < 0)
            {
                return null;
            }
            EasyLinkerSDK.Model.Client.Query.QueryResult result = new EasyLinkerSDK.Model.Client.Query.QueryResult()
            {
                Device = _clientInfo.DeviceType,
                Uid = _clientInfo.UserId,
                Key = _clientInfo.Key,
                ProtocolType = _clientInfo.ProtocolType,
                Type = message.Type,
                Action = ActionName.Query,
                MessageId = message.MessageId,
                DeviceId = message.DeviceId,
                Time = Time.Timestamp(),
                Data = new EasyLinkerSDK.Model.Client.Query.QueryResultData()
                {
                    Values = values,
                },
            };
            return result;
        }


    }
}
